﻿using System.Collections;
using System.Xml;
using RAP.Framework.Libary.Utils.Collections.Dictionary;

namespace RAP.Framework.Libary.Utils
{
    /// <summary>
    /// XmlNode对象扩展
    /// </summary>
    public static partial class Extensions
    {
        #region XmlNode扩展

        /// <summary>
        /// 将指定的Xml节点对象转换成指定IDictionary对象的属性
        /// </summary>
        /// <param name="section"></param>
        /// <param name="target">目标键值对象</param>
        /// <returns></returns>
        public static IDictionary ToDictionary( this XmlNode section, IDictionary target = null )
        {
            if ( target == null )
            {
                target = new ListDictionary( );
            }
            section.Attributes.ToDictionary( target );
            foreach ( XmlNode node in section.ChildNodes )
            {
                string nodeName = node.Name;
                switch ( node.NodeType )
                {
                    case XmlNodeType.Element:
                        if ( node.IsTextNode( ) )
                        {
                            target[ nodeName ] = node.InnerText;
                        }
                        else
                        {
                            IDictionary childDict = node.ToDictionary( );
                            object nodeTarget = target[ nodeName ];
                            if ( nodeTarget == null )
                            {
                                target[ nodeName ] = childDict;
                            }
                            else if ( nodeTarget is IDictionary )
                            {
                                //如果已存在相同键值的对象，则处理成数组
                                IList list = null;
                                list = new ArrayList( );
                                list.Add( nodeTarget );
                                target[ nodeName ] = list;
                            }
                            else if ( nodeTarget is IList )
                            {
                                //如果已经是集合，则添加到集合
                                IList list = nodeTarget as IList;
                                list.Add( childDict );
                            }
                        }
                        break;

                    case XmlNodeType.Text:
                    case XmlNodeType.CDATA:
                        nodeName = node.ParentNode.Name;
                        if ( target[ nodeName ] == null )
                        {
                            target[ nodeName ] = node.Value;
                        }
                        else
                        {
                            target[ "Text" ] = node.Value;
                        }
                        break;
                }
            }
            return target;
        }

        /// <summary>
        /// 判断某个XML节点是否是纯文本节点
        /// </summary>
        /// <param name="section"></param>
        /// <returns></returns>
        public static bool IsTextNode( this XmlNode section )
        {
            if ( section == null || section.ChildNodes.Count == 0 )
            {
                return false;
            }
            foreach ( XmlNode node in section.ChildNodes )
            {
                switch ( node.NodeType )
                {
                    case XmlNodeType.CDATA:
                    case XmlNodeType.Comment:
                    case XmlNodeType.Text:
                        break;

                    case XmlNodeType.Element:
                        return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 向指定XML节点添加属性
        /// </summary>
        /// <param name="node"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static XmlNode AddAttribute( this XmlNode node, string name, string value )
        {
            var attr = node.OwnerDocument.CreateAttribute( name );
            attr.Value = value;
            node.Attributes.Append( attr );
            return node;
        }

        #endregion XmlNode扩展
    }
}
